○DLLの作成
Win32 Dynamic-Link Library
単純なDLLプロジェクトを選択
DllMain の前に以下を追加
-----------------------------------ここから-----------------------------------
int intPos;
extern "C" __declspec(dllexport) int getInt(void){
return intPos;
}
extern "C" __declspec(dllexport) void setInt(int b){
intPos=b;
}
extern "C" __declspec(dllexport) void mbox(char*a){
::MessageBox(NULL,a,"hello", MB_OK);
}
#include <string.h>
char str[1024]="";
extern "C" __declspec(dllexport) char* out(char*a,char*b){
strcat(str,a);
strcat(str,b);
return str;
}
----------------------------------ここまで-------------------------------------
ビルドしてDLLを作成します。
○DLLの動的呼び出し
上で作成した ○○○.dll ファイルを実行ファイルのあるディレクトリに移動します。
void DllCall()
{
typedef int (*GETINT)(void); //関数ポインタの構造体の宣言
typedef void (*SETINT)(int);
typedef void(*MBOX)(char*);
typedef char*(*OUTCHAR)(char*,char*);
//DLLをロードできないときは次のをためしてみる
//typedef int (__stdcall*GETINT)(void);
//アドレス空間内にマップする
HINSTANCE hDllInstance = ::LoadLibrary("testdll.dll");//DLLを指定
// エクスポートされた関数のアドレスを取得
GETINT getInt=(GETINT)::GetProcAddress(hDllInstance, "getInt"); //関数ポインタとDLLの関数の結びつけ
SETINT setInt=(SETINT)::GetProcAddress(hDllInstance, "setInt");
MBOX mbox=(MBOX)::GetProcAddress(hDllInstance, "mbox");
OUTCHAR out=(OUTCHAR)::GetProcAddress(hDllInstance, "out");
printf("%s\n",out("aa","bb"));//後は普通の関数のように呼び出せます。
FreeLibrary(hDllInstance);//開放
}
○呼び出し規約の違い
関数の引数はスタックに積まれて渡されますが、最後に誰がスタックを戻すかにより
呼び出し規則が変わります。
■DLLのソース
//スタックの後処理を呼び出し側が行う呼び出し規則
extern "C" __declspec(dllexport) int __cdecl a(int i){
return i;
}
//スタックの後処理を関数側が行う呼び出し規則
//WINDOWSのAPIなどと同じ呼び出し規則
extern "C" __declspec(dllexport) int __stdcall b(int i){
return i;
}
■上のDLLを呼び出すプログラム
呼び出し規則によりDLLを呼び出す側の対応も必要になります
typedef int (__cdecl *A)(int); //関数ポインタの構造体の宣言
typedef int (__stdcall *B)(int); //関数ポインタの構造体の宣言
HINSTANCE hDllInstance = LoadLibrary("test.dll");//DLLを指定
A a=(A)GetProcAddress(hDllInstance, "a");
B b=(B)GetProcAddress(hDllInstance, "_b@4");//エクスポートされた名前を調べる必要がある
printf("%d\n",a(1));
printf("%d\n",b(2));
FreeLibrary(hDllInstance);
エキスポートされた名前を調べるには、このプログラムを使いました
DLLの関数名を表示 実行ファイル+ソース
○APIもDLLのため、呼び出し規則をあわせれば同様に呼び出せます
次のプログラムではMessageBoxAをDLLの呼び出しと同じように呼び出します
typedef int (__stdcall *FUNC)(HWND,LPCSTR,LPCSTR,UINT); //関数ポインタの構造体の宣言
HINSTANCE hDllInstance = LoadLibrary("user32.dll");//DLLを指定
FUNC func=(FUNC)GetProcAddress(hDllInstance, "MessageBoxA");
func(NULL,"a","b",1);
▲トップページ
>
Windows と C++